 /**
 * @file tal_data_send.h
 * @brief Common process - data send
 * @version 1.0.0
 * @date 2021-09-09
 *
 * @copyright Copyright 2018-2021 Tuya Inc. All Rights Reserved.
 *
 */
#ifndef __TAL_DATA_SEND_H__
#define __TAL_DATA_SEND_H__


#ifdef __cplusplus
    extern "C" {
#endif

#include "tuya_cloud_types.h"
#include "tuya_zigbee_stack.h"


/**
 * @enum zigbee send data status 
 */
typedef enum {
    SEND_ST_OK = 0,         ///< Successful delivery
    SEND_ST_ERR,            ///< Transmission failed due to network failure
    SEND_ST_MEMORY_ERR,     ///< Send failed due to memory error
    SEND_ST_QUEUE_FULL_ERR, ///< Send failed because the queue was full
    SEND_ST_NO_NETWORK,     ///< Sending failed due to no network
    SEND_ST_ADDR_MODE_ERR,  ///< Delivery failed due to address error
    SEND_ST_SEND_DOING,     ///< Waitting send
} TAL_SEND_ST_E;

/**
 * @enum zigbee send data mode 
 */
typedef enum {
    SEND_MODE_DEV = 0,      ///< Send to device, short address is required
    SEND_MODE_GROUP,        ///< Send a multicast message, group address is required
    SEND_MODE_BINDING,      ///< Sent according to the binding table, No short address is required
} TAL_SEND_MODE_E;

/**
 * @enum the reliable behavior of sending data
 */
typedef enum {
    QOS_0 = 0,              ///< There is no retransmission mechanism
    QOS_1,                  ///< There is retransmission mechanism
    QOS_VIP_0,              ///< Data is sent first, there is no retransmission mechanism
    QOS_VIP_1,              ///< Data is sent first, there is retransmission mechanism
} TAL_SEND_QOS_E;

/**
 * @enum way to clear the send queue
 */
typedef enum {
    ZG_CLEAR_ALL_DATA = 0,  ///< Clear all queue data
    ZG_CLEAR_LATEST_DATA,   ///< Clear the lastest data
    ZG_CLEAR_ALL_SAME_DATA, ///< Clear all the same data
    ZG_CLEAR_ALL_ZCL_ID,    ///< Clear all the data with the same ZCL ID
} TAL_ZG_CLEAR_TYPE_E;

/**
 * @enum group addr struct
 */
typedef struct {
    UINT8_T  src_ep;        ///< source endpoint
    UINT8_T  dst_ep;        ///< destination endpoint
    UINT16_T cluster_id;    ///< cluster id
    UINT16_T group_id;      ///< group addr
} TAL_GROUP_ADDR_T;

/**
 * @enum bind addr struct
 */
typedef struct {
    UINT8_T  src_ep;        ///< source endpoint
    UINT16_T cluster_id;    ///< cluster id
} TAL_BIND_ADDR_T;

/**
 * @enum device addr struct
 */
typedef struct {
    UINT8_T  src_ep;        ///< source endpoint
    UINT8_T  dst_ep;        ///< destination endpoint
    UINT16_T cluster_id;    ///< cluster id
    UINT16_T dst_addr;      ///< destination nwk addr
} TAL_DEV_ADDR_T;

/**
 * @enum zigbee send addr struct
 */
typedef struct {
    TAL_SEND_MODE_E mode;       ///< send data mode
    union {
        TAL_DEV_ADDR_T   dev;   ///< send data directly to device(include gateway) , dst_addr > 0xFFFC indicates broadcast
        TAL_BIND_ADDR_T  bind;  ///< send data to device through binding table, binding relationship must be established first
        TAL_GROUP_ADDR_T group; ///< sending data through multicast, need to fill in the group address
        // TAL_GW_ADDR_T    gw;
    } type;
} TAL_ZG_ADDR_T;

/**
 * @enum zigbee attribute value
 */
typedef struct {
    UINT16_T attr_id;           ///< attribute id
    ZG_ATTR_TYPE_E type;        ///< attribute type
    UINT8_T  size;              ///< attribute value len
    UINT8_T  value[8];          ///< attribute value
} TAL_ATTR_VALUE_T;

/**
 * @enum zigbee attribute data list
 */
typedef struct {
    UINT8_T attr_sum;           ///< attribute number
    TAL_ATTR_VALUE_T attr[8];   ///< attribute instantiation
} TAL_ZG_DATA_T;

/**
 * @enum zigbee private data(include command data)
 */
typedef struct {
    UINT8_T len;                ///< data length
    UINT8_T data[64];           ///< data buff
} TAL_PRIVATE_DATA_T;

/**
 * @enum zigbee data for sending
 */
typedef struct {
    UINT16_T delay_time;                ///< send delay time with ms
    UINT16_T random_time;               ///< send random times with ms
    UINT16_T manu_code;                 ///< manufacturer code
    UINT8_T  manu_spec;                 ///< 1: for enable manufacturer code
    UINT8_T  zcl_id;                    ///< applicaiton sequence number(0x00~0xF0 for user, 0xF0~0xFF for SDK)
    UINT8_T  command_id;                ///< zcl command id, the detail in tuya_zigbee_commmand.h
    ZG_ZCL_FRAME_TYPE_E frame_type;     ///< zcl frame type
    ZG_ZCL_DATA_DIRECTION_E direction;  ///< data transmission direction
    TAL_SEND_QOS_E qos;                 ///< data service quality
    TAL_ZG_ADDR_T  addr;                ///< zigbee data address
    union {
        TAL_ZG_DATA_T      zg;
        TAL_PRIVATE_DATA_T private;
    } data;
} TAL_ZG_SEND_DATA_T;

typedef VOID_T (*TAL_SEND_RESULT_CB)(TAL_SEND_ST_E, TAL_ZG_SEND_DATA_T *);

/**
 * @brief check send data is busy
 *
 * @param[in] none
 * @return TRUE: send busy
 */
BOOL_T tal_zg_send_data_is_busy(VOID_T);

/**
 * @brief clear send cache data
 *
 * @param[in] type: clear type
 * @param[in] args: point to the sending data to be deleted
 * @return TRUE: none
 */
VOID_T tal_zg_clear_send_data(TAL_ZG_CLEAR_TYPE_E type, VOID_T *args);

/**
 * @brief receive ack handle
 *
 * @param[in] seq:        sequence number of received data 
 * @param[in] endpoint:   endpoint id
 * @param[in] cluster_id: cluster id
 * @return TRUE: none
 */
VOID_T tal_zg_receive_ack_handle(UINT8_T seq, UINT8_T endpoint, UINT16_T cluster_id);

/**
 * @brief receive ack handle
 *
 * @param[in] pdata:    point data to be send
 * @param[in] callback: send result callback
 * @param[in] timeout:  data send timeout
 * @return TRUE: none
 */
VOID_T tal_zg_send_data(TAL_ZG_SEND_DATA_T *pdata, TAL_SEND_RESULT_CB callback, UINT_T timeout);


#ifdef __cplusplus
}
#endif

#endif
